package com.huike.clues.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.huike.clues.domain.*;
import com.huike.clues.domain.dto.TbClueCreateDTO;
import com.huike.clues.domain.dto.TbPageClueDTO;
import com.huike.clues.domain.dto.TbRuleListDTO;
import com.huike.clues.domain.dto.TbUserGainClueDTO;
import com.huike.clues.domain.vo.FalseClueVo;
import com.huike.clues.domain.vo.PageClueVO;
import com.huike.clues.mapper.*;
import com.huike.clues.service.TbClueService;
import com.huike.common.constant.ErrorMessageConstants;
import com.huike.common.core.domain.entity.SysUserDTO;
import com.huike.common.core.page.TableDataInfo;
import com.huike.common.exception.BaseException;
import com.huike.common.utils.SecurityUtils;
import com.huike.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 93238
 * @description 针对表【tb_clue(线索)】的数据库操作Service实现
 * @createDate 2023-10-12 06:35:46
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class TbClueServiceImpl extends ServiceImpl<TbClueMapper, TbClue> implements TbClueService {

    private final SysUserMapper sysUserMapper;

    private final TbAssignRecordMapper tbAssignRecordMapper;

    private final TbRulePoolMapper tbRulePoolMapper;

    private final TbClueTrackRecordMapper tbClueTrackRecordMapper;

    private final TbClueMapper mapper;

    /**
     * 新增线索
     */
    @Override
    @Transactional
    public void createClue(TbClueCreateDTO dto) {
        // 查询唯一性
        LambdaQueryWrapper<TbClue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TbClue::getPhone, dto.getPhone());
        TbClue clueDB = getOne(queryWrapper);
        if (clueDB != null) {
            throw new BaseException(ErrorMessageConstants.CLUE_ALREADY_EXITS);
        }

        // 新增线索
        TbClue clue = new TbClue();
        BeanUtils.copyProperties(dto, clue);
        // 判断拥有的线索是否达到最大值
        SysUserDTO user = sysUserMapper.selectUserById(SecurityUtils.getUserId());
        LambdaQueryWrapper<TbAssignRecord> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(TbAssignRecord::getType, 0);
        queryWrapper1.eq(TbAssignRecord::getLatest, 1);
        queryWrapper1.eq(TbAssignRecord::getUserId, user.getUserId());
        LambdaQueryWrapper<TbRulePool> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.select(TbRulePool::getMaxNunmber);
        queryWrapper2.eq(TbRulePool::getType, 0);
        if (tbAssignRecordMapper.selectCount(queryWrapper1) + 1 > tbRulePoolMapper.selectOne(queryWrapper2).getMaxNunmber()) {
            clue.setTransfer("1");
        }
        clue.setCreateBy(SecurityUtils.getUsername());
        clue.setCreateTime(new Date());
        clue.setUpdateTime(new Date());
        if (!save(clue)) {
            throw new BaseException(ErrorMessageConstants.FAILED_TO_ADD_CLUE);
        }

        // 新增分配
        tbAssignRecordMapper.insert(TbAssignRecord.builder()
                .assignId(clue.getId())
                .userId(SecurityUtils.getUserId())
                .userName(SecurityUtils.getUsername())
                .deptId(user.getDeptId())
                .createTime(new Date())
                .createBy(SecurityUtils.getUsername())
                .latest("1")
                .type("0")
                .build());
    }

    /**
     * 批量分配
     *
     * @param dto 传入批量分配的id集合以及分配给哪个用户的id
     */
    @Override
    @Transactional
    public void assignment(TbUserGainClueDTO dto) {
        // 判断分配到的用户是否存在
        SysUserDTO user = sysUserMapper.selectUserById(dto.getUserId());
        if (user == null) {
            throw new BaseException(ErrorMessageConstants.USER_DOES_NOT_EXIST);
        }

        // 判断线索集合中的客户是否存在
        LambdaQueryWrapper<TbClue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbClue::getId, dto.getIds());
        if (count(queryWrapper) != dto.getIds().size()) {
            throw new BaseException(ErrorMessageConstants.CLUE_DOES_NOT_EXIST);
        }

        // 判断用户所持有的线索数量是否超过上限
        LambdaQueryWrapper<TbAssignRecord> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(TbAssignRecord::getUserId, dto.getUserId());
        queryWrapper2.eq(TbAssignRecord::getLatest, 1);
        queryWrapper2.eq(TbAssignRecord::getType, 0);
        LambdaQueryWrapper<TbRulePool> queryWrapper3 = new LambdaQueryWrapper<>();
        queryWrapper3.select(TbRulePool::getMaxNunmber);
        queryWrapper3.eq(TbRulePool::getType, 0);
        int count = tbRulePoolMapper.selectOne(queryWrapper3).getMaxNunmber() - (tbAssignRecordMapper.selectCount(queryWrapper2) + dto.getIds().size());
        if (count < 0) {
            throw new BaseException(ErrorMessageConstants.HOLDING_TOO_MANY_CLUE);
        }

        // 分配记录表的least字段设置为0
        tbAssignRecordMapper.updateLeastByIds(dto.getIds());

        // 分配记录表插入新的记录
        tbAssignRecordMapper.insertRecords(dto.getIds().stream().map(i ->
                TbAssignRecord.builder()
                        .assignId(i)
                        .userId(SecurityUtils.getUserId())
                        .userName(SecurityUtils.getUsername())
                        .deptId(user.getDeptId())
                        .createTime(new Date())
                        .createBy(SecurityUtils.getUsername())
                        .latest("1")
                        .type("0")
                        .build()
        ).collect(Collectors.toList()));

        // 更新线索表
        mapper.updateStatusByIds(TbClue.builder()
                .status("2")
                .updateTime(new Date())
                .build(), dto.getIds());
    }

    /**
     * 设置当前线索为伪线索
     *
     * @param id          线索id
     * @param falseClueVo 原因和跟进记录
     */
    @Override
    @Transactional
    public void falseClue(Long id, FalseClueVo falseClueVo) {
        // 判断当前线索是否存在
        TbClue clue = getById(id);
        if (clue == null) {
            throw new BaseException(ErrorMessageConstants.CLUE_DOES_NOT_EXIST);
        }

        // 判断当前线索为伪线索的次数
        // 判断是否上报次数是否为3，是则删除线索
        if (clue.getFalseCount() == 3) {
            clue.setEndTime(new Date());
            clue.setStatus("4");
            clue.setFalseCount(4);
            clue.setUpdateTime(new Date());
            if (!updateById(clue)) {
                throw new BaseException(ErrorMessageConstants.FAILED_TO_UPDATE_CLUE);
            }
        } else {
            // 不是则进入线索池
            if (tbClueTrackRecordMapper.insert(TbClueTrackRecord.builder()
                    .clueId(clue.getId().toString())
                    .createBy(SecurityUtils.getUsername())
                    .record(falseClueVo.getRemark())
                    .type("1")
                    .falseReason(falseClueVo.getReason())
                    .build()) != 1) {
                throw new BaseException(ErrorMessageConstants.FAILED_TO_ADD_CLUE_TRACK_RECORD);
            }
            // 修改线索信息
            clue.setStatus("4");
            clue.setFalseCount(clue.getFalseCount() + 1);
            clue.setUpdateTime(new Date());
            if (!updateById(clue)) {
                throw new BaseException(ErrorMessageConstants.FAILED_TO_UPDATE_CLUE);
            }
        }
    }

    /**
     * 批量捞取
     *
     * @param dto 传入批量捞取的线索id集合以及分配给捞取用户的id
     */
    @Override
    public void gain(TbUserGainClueDTO dto) {
        // 判断分配到的用户是否存在
        SysUserDTO user = sysUserMapper.selectUserById(dto.getUserId());
        if (user == null) {
            throw new BaseException(ErrorMessageConstants.USER_DOES_NOT_EXIST);
        }

        // 判断线索集合中的客户是否存在
        LambdaQueryWrapper<TbClue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbClue::getId, dto.getIds());
        if (count(queryWrapper) != dto.getIds().size()) {
            throw new BaseException(ErrorMessageConstants.CLUE_DOES_NOT_EXIST);
        }

        // 判断用户所持有的线索数量是否超过上限
        LambdaQueryWrapper<TbAssignRecord> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(TbAssignRecord::getUserId, dto.getUserId());
        queryWrapper2.eq(TbAssignRecord::getLatest, 1);
        queryWrapper2.eq(TbAssignRecord::getType, 0);
        LambdaQueryWrapper<TbRulePool> queryWrapper3 = new LambdaQueryWrapper<>();
        queryWrapper3.eq(TbRulePool::getType, 0);
        TbRulePool tbRulePool = tbRulePoolMapper.selectOne(queryWrapper3);
        int count = tbRulePool.getMaxNunmber() - (tbAssignRecordMapper.selectCount(queryWrapper2) + dto.getIds().size());
        if (count < 0) {
            throw new BaseException(ErrorMessageConstants.HOLDING_TOO_MANY_CLUE);
        }

        // 获取限定反复捞取的时限
        Integer time = tbRulePool.getRepeatGetTime();
        String unit = tbRulePool.getRepeatType();
        if ("0".equals(unit)) {
            time *= 1;
        } else if ("1".equals(unit)) {
            time *= 7;
        } else if ("2".equals(unit)) {
            time *= 30;
        }

        // 获取传入用户在线索集合中最近设置为伪线索的线索时间
        TbAssignRecord clue = tbClueTrackRecordMapper.getClueOfLatestFalse(dto.getUserId(), dto.getIds());
        if (clue != null &&
                (System.currentTimeMillis() - clue.getCreateTime().getTime() / (24 * 60 * 60 * 1000)) < time) {
            throw new BaseException(ErrorMessageConstants.FAILED_TO_REPEAT_GAIN);
        }

        // 分配记录表的least字段设置为0
        tbAssignRecordMapper.updateLeastByIds(dto.getIds());

        // 分配记录表插入新的记录
        tbAssignRecordMapper.insertRecords(dto.getIds().stream().map(i ->
                TbAssignRecord.builder()
                        .assignId(i)
                        .userId(SecurityUtils.getUserId())
                        .userName(SecurityUtils.getUsername())
                        .deptId(user.getDeptId())
                        .createTime(new Date())
                        .createBy(SecurityUtils.getUsername())
                        .latest("1")
                        .type("0")
                        .build()
        ).collect(Collectors.toList()));

        // 更新线索表
        mapper.updateStatusByIds(TbClue.builder()
                .status("2")
                .updateTime(new Date())
                .build(), dto.getIds());
    }

    /**
     * 更新线索
     */
    @Override
    public void updateClue(TbClue clue) {
        mapper.updateClue(clue);
    }

    /**
     * 查询线索管理列表
     *
     * @param dto 查询条件
     * @return 返回线索集合
     */
    @Override
    public TableDataInfo<List<PageClueVO>> getPageClue(TbRuleListDTO dto) {
        /* Page<TbClue> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<TbClue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dto.getId() != null, TbClue::getId, dto.getId());
        queryWrapper.eq(dto.getPhone() != null, TbClue::getPhone, dto.getPhone());
        queryWrapper.eq(dto.getChannel() != null, TbClue::getChannel, dto.getChannel());
        queryWrapper.eq(dto.getStatus() != null, TbClue::getStatus, dto.getStatus());
        if (dto.getParams() != null && !StringUtils.isEmpty(dto.getParams().get("beginCreateTime").toString()) && !StringUtils.isEmpty(dto.getParams().get("endCreateTime").toString())) {
            queryWrapper.between(TbClue::getCreateTime, dto.getParams().get("beginCreateTime"), dto.getParams().get("endCreateTime"));
        }
        page(page, queryWrapper);
        TableDataInfo<List<TbClue>> res = new TableDataInfo<>(page.getRecords(), page.getTotal());
        res.setCode(200);
        return res; */
        PageHelper.startPage(dto.pageNum, dto.getPageSize());
        TbPageClueDTO tbPageClueDTO = new TbPageClueDTO();
        BeanUtils.copyProperties(dto, tbPageClueDTO);
        if (!StringUtils.isEmpty((String) dto.getParams().get("beginCreateTime"))) {
            tbPageClueDTO.setBeginCreateTime((String) dto.getParams().get("beginCreateTime"));
        }
        if (!StringUtils.isEmpty((String) dto.getParams().get("endCreateTime"))) {
            tbPageClueDTO.setBeginCreateTime((String) dto.getParams().get("beginCreateTime"));
        }
        Page<PageClueVO> page = mapper.pageClue(tbPageClueDTO);
        if (page.getResult() != null && page.getTotal() > 0) {
            page.getResult().forEach(i -> {
                TbActivity info = mapper.getActivityInfoByClueId(i.getId());
                if (info != null) {
                    i.setActivityName(info.getName());
                    i.setActivityInfo(info.getInfo());
                }
            });
        }
        log.info("Get pageResult: {}", page.getResult());
        TableDataInfo<List<PageClueVO>> res = new TableDataInfo<>(page.getResult(), page.getTotal());
        res.setCode(200);
        return res;
    }

    /**
     * 获取线索池
     *
     * @param dto 查询条件
     * @return 返回线索池
     */
    @Override
    public TableDataInfo<List<PageClueVO>> getCluePool(TbRuleListDTO dto) {
        PageHelper.startPage(dto.pageNum, dto.getPageSize());
        TbPageClueDTO tbPageClueDTO = new TbPageClueDTO();
        BeanUtils.copyProperties(dto, tbPageClueDTO);
        if (!StringUtils.isEmpty((String) dto.getParams().get("beginCreateTime"))) {
            tbPageClueDTO.setBeginCreateTime((String) dto.getParams().get("beginCreateTime"));
        }
        if (!StringUtils.isEmpty((String) dto.getParams().get("endCreateTime"))) {
            tbPageClueDTO.setBeginCreateTime((String) dto.getParams().get("beginCreateTime"));
        }
        Page<PageClueVO> page = mapper.pagePool(tbPageClueDTO);
        if (page.getResult() != null && page.getTotal() > 0) {
            page.getResult().forEach(i -> {
                TbActivity info = mapper.getActivityInfoByClueId(i.getId());
                if (info != null) {
                    i.setActivityName(info.getName());
                    i.setActivityInfo(info.getInfo());
                }
            });
        }
        log.info("Get pageResult: {}", page.getResult());
        TableDataInfo<List<PageClueVO>> res = new TableDataInfo<>(page.getResult(), page.getTotal());
        res.setCode(200);
        return res;
    }

    /**
     * 根据id获取线索信息
     *
     * @param id 线索id
     * @return 返回线索信息
     */
    @Override
    public PageClueVO getInfoById(Long id) {
        PageClueVO res = tbClueTrackRecordMapper.getInfoById(id);
        if (res != null) {
            TbActivity info = mapper.getActivityInfoByClueId(res.getId());
            if (info != null) {
                res.setActivityName(info.getName());
                res.setActivityInfo(info.getInfo());
            }
        }
        log.info("Get res: {}", res);
        return res;
    }

}




